#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include "Agent.h"

#ifndef AIRPORT_H
#define AIRPORT_H
using namespace std;

class Airplane;
class Airport;
class Agent;
struct State;
struct Edge;
struct State
{
    int speed;
    int congestionFirst;
    int congestionSecond;
    int congestionThird;
    int routedFirst;
    int routedSecond;
    int routedThird;
    int timeLeft;

    bool operator== (State input) {

        return  ((input.speed==speed) && (input.congestionFirst==congestionFirst) &&
        (input.congestionSecond == congestionSecond) &&  (input.congestionThird == congestionThird) &&
        (input.routedFirst == routedFirst) && (input.routedSecond == routedSecond) &&
        (input.routedThird == routedThird) && (input.timeLeft == timeLeft));

}
};

enum AirplaneState
{
    STANDBY,
    TRAVELING,
    LANDING,
    LANDED
};

enum Actions
{
    RouteFirst,
    RouteSecond,
    RouteThird,
    Delay
};

class Airplane
{
public:
    Airplane(int airplaneNumInput);
    virtual ~Airplane();
    int airplaneNum;

    AirplaneState state;

    State* prevState;
    Actions prevAction;

    vector<int> edgeTravel;
    double edgeLoc;
    double speed;

    double milesInTow;

    int departureTime;
    int arrivalTime;
    int totalTime;

    int departureAirport;
    int arrivalAirport;
    int currentAirport;

    bool justLanded;
    bool oneStop;

    void updatePosition(Edge &curEdge);
    vector<int> getActions(vector<Airport> airports, vector<vector<vector<vector<int> > > > lookupTable);
    void takeAction(Actions a, vector<vector<vector<vector<int> > > > lookupTable);
protected:
private:
};

class Airport
{
public:
    Airport();
    virtual ~Airport();

    vector<Edge> airportRoutes;
    double congestionCost;
    int airportNum;
    int planesInAirspaceMax;
    int planesInAirspace;
    int airplaneLandingTimer;
    vector<Airplane> airplanesLanded;
    vector<Airplane*> airplanesLanding;
    Agent *agent;

    void updateCongestion(vector<vector<Edge> > edges);
    Actions getAction(State* state, vector<int> possibleActions);
protected:
private:
};

struct Edge
{
    int edgeNum;
    double length;
    Airport *fromAirport;
    Airport *toAirport;
    vector<Airplane*> airplanes;
    vector<Airplane> airplaneDepatureQueue;
};

struct less_than_key
{
    inline bool operator() (const Airplane& struct1, const Airplane& struct2)
    {
        return (struct1.departureTime < struct2.departureTime);
    }
};

struct dataStruct
{
    State* prevState;
    Actions prevAction;
    State* state;
    Actions action;
    int airportNum;
};
#endif // AIRPORT_H
